package com.ease.script.rhino;

import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptException;

import com.ease.common.util.Assertion;
import com.ease.common.util.Detect;

/**
 * 
 * @author nathanleewei
 * 
 */
public class ScriptEngineTemplate extends Detect {

	public static final String SCRIPT_ENGINE_JAVASCRIPT = "javascript";

	static {
		// http://www.mozilla.org/rhino/tutorial.html
		// Object wrappedOut = Context.javaToJS(System.out, scope);
		// ScriptableObject.putProperty(scope, "out", wrappedOut);
	}

	private ScriptEngine scriptEngine;

	private ApplicationContextBindings applicationContextBindings;

	//
	// public Object invokeFunction(String script, BindingsCallback
	// bindingsCallback) {
	//
	// Bindings bindings = new NestedBindings(applicationContextBindings);
	// bindingsCallback.bind(bindings);
	//
	// try {
	// scriptEngine.eval(script, bindings);
	//
	// Invocable invocable = (Invocable) scriptEngine;
	// return invocable.invokeFunction("max", "1", "0");
	//
	// } catch (Exception e) {
	// e.printStackTrace();
	// throw new RuntimeException(script + "/n" + e);
	// }
	// }

	public Object evaluate(String script, boolean wrapFunction, BindingsCallback bindingsCallback) {
		return evaluate(wrapFunction(script), bindingsCallback);
	}

	public Object evaluate(String script, BindingsCallback bindingsCallback) {

		Assertion.notEmpty(script, "script not found");

		Bindings bindings = new NestedBindings(applicationContextBindings);
		bindingsCallback.bind(bindings);

		try {
			return scriptEngine.eval(script, bindings);
		} catch (ScriptException e) {
			e.printStackTrace();
			throw new RuntimeException(script + "/n" + e);
		}
	}

	private static String wrapFunction(String script) {
		return "(function(){" + script + "})();";
	}

	/**
	 * @return the scriptEngine
	 */
	public ScriptEngine getScriptEngine() {
		return scriptEngine;
	}

	/**
	 * @param scriptEngine
	 *            the scriptEngine to set
	 */
	public void setScriptEngine(ScriptEngine scriptEngine) {
		this.scriptEngine = scriptEngine;
	}

	/**
	 * @return the applicationContextBindings
	 */
	public ApplicationContextBindings getApplicationContextBindings() {
		return applicationContextBindings;
	}

	/**
	 * @param applicationContextBindings
	 *            the applicationContextBindings to set
	 */
	public void setApplicationContextBindings(ApplicationContextBindings applicationContextBindings) {
		this.applicationContextBindings = applicationContextBindings;
	}

}
